package dyyx;

import java.util.Date;

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException.NoNodeException;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.ZooKeeper;


/**
 * 创建 临时节点 成功的 获取锁 ， 不断的轮询改节点数据 ， 没有使用 watch 机制
 * @author dugang
 *
 */
public class LockTest {

	private static final String LOCK_PATH = "/lock1";

	public static void main(String[] args) throws Exception {
		System.out.println("LockTest," + new Date());

		int num = 3;
		Client[] clients = new Client[num];
		for (int i = 0; i < num; i++) {
			clients[i] = new Client("id" + i);
		}
		for (int i = 0; i < num; i++) {
			clients[i].start();
		}

		Utils.doSleep(1000000);

	}

	private static class Client extends Thread {

		private final ZooKeeper client;
		private final String id;
		private int runCount = 0;


		public Client(String id) throws Exception {
			this.id = id;
			client = ZkUtils.getClient();
		}

		private boolean tryLock() {
			try {
				String createResult = client.create(LOCK_PATH, id.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE,
						CreateMode.EPHEMERAL);
				System.out.println(id + ".createResult=" + createResult + "," + Utils.getTimeString());

				return true;
			} catch (Throwable e) {
				// org.apache.zookeeper.KeeperException$NodeExistsException:KeeperErrorCode
				// = NodeExists for /zk_test
				System.out.println(id + ".create error," + e + "," + Utils.getTimeString());
				return false;
			}
		}

		public void run() {

			while (true) {
				long sleepTime = Utils.getRandomInt(1000);
				Utils.doSleep(sleepTime);

				byte[] bytes = null;
				boolean nodeNotExist = false;
				try {
					// 读取最新值 
					client.sync(LOCK_PATH, null, null);
					bytes = client.getData(LOCK_PATH, false, null);
				} catch (Throwable e) {
					// error,org.apache.zookeeper.KeeperException$NoNodeException
					System.out.println(id + ".getData error," + e + "," + Utils.getTimeString());
					if (e instanceof NoNodeException) {
						nodeNotExist = true;
					}
				}

				// 节点不存在 立马争抢
				if (nodeNotExist) {
					if(tryLock()){
						runCount = 0;
						runCount++;
						// do something
						
						Utils.doSleep(1000);	
					}
				}

				String lockid = null;
				if (bytes != null) {
					lockid = new String(bytes);
				}

				if (id.equals(lockid)) {
					System.out.println("locked,id=" + id + ",runCount="+runCount+"," + Utils.getTimeString());
					
					Utils.doSleep(1000);
					runCount++;
					
					if(runCount>=10){
						//  主动 释放锁
						
						try{
						    client.delete(LOCK_PATH, -1);
						    runCount = 0;
						    
							System.out.println("lock release,id=" + id + ",runCount="+runCount+"," + Utils.getTimeString());

						    
						}catch(Throwable e){
							System.out.println(id+"delete error," + e + "," + Utils.getTimeString());
						}
						
					}

					
					continue;
				} else {
					System.out.println("no lock,id=" + id + ",lockid=" + lockid + "," + Utils.getTimeString());
					Utils.doSleep(2000);

					if(tryLock()){
						runCount = 0;
						runCount++;
						// do something
						
						Utils.doSleep(1000);	
					}
					
					continue;
				}

			}

		}
	}

}
